#include <cpp_primer.h>

using namespace std;

class QueryResult;

class TextQuery {
public:
    using line_no = vector<string>::size_type;
    TextQuery(ifstream&);
    QueryResult query(const string&) const;

private:
    // 输入文件
    shared_ptr<vector<string>> file;

    // 每个单词到它所在的行号的集合的映射
    map<string, shared_ptr<set<line_no>>> wm;
};

TextQuery::TextQuery(ifstream &is) : file(new vector<string>)
{
    string text;
    while(getline(is, text)) {
        file->push_back(text);
        int n = file->size() - 1;   // 当前行号
        istringstream line(text);
        string word;
        while(line >> word) {
            auto &lines = wm[word]; // lines是一个shared_ptr
            if(!lines)
                lines.reset(new set<line_no>);  // 第一次遇到这个单词，分配一个新的set
            lines->insert(n);
        }
    }
}

class QueryResult {
    friend ostream& print(ostream&, const QueryResult&);
public:
    using line_no = vector<string>::size_type;

    QueryResult(string s, shared_ptr<set<line_no>> p,
                shared_ptr<vector<string>> f): 
        sought(s), lines(p), file(f) {  }

    using Iter = set<line_no>::iterator;
    Iter begin() const { return lines->begin();  }
    Iter end()const { return lines->end();  }
    shared_ptr<vector<string>> get_file() const
    {
        return make_shared<vector<string>>(file);
    }

private:
    string sought;  // 查询单词
    shared_ptr<set<line_no>> lines; // 出现的行号
    shared_ptr<vector<string>> file;    // 输入文件
};

QueryResult TextQuery::query(const string &sought) const
{
    // 如果未找到，返回指向一个set的指针
    // static只声明一次，与什么sought无关
    static shared_ptr<set<line_no>> nodata(new set<line_no>);
    // 使用find查找，下标会加入新元素
    auto loc = wm.find(sought);
    if(loc == wm.end())
        return QueryResult(sought, nodata, file);
    else
        return QueryResult(sought, loc->second, file);
}

string make_plural(size_t ctr, const string &word, const string &ending)
{
    return (ctr > 1) ? word + ending : word;
}

ostream &print(ostream &os, const QueryResult &qr)
{
    os << qr.sought << " occurs " << qr.lines->size() << " "
        << make_plural(qr.lines->size(), "time", "s") << endl;
    for(auto num : *qr.lines)
        os << "\t(line " << num + 1 << ") "
            << *(qr.file->begin() + num) << endl;
    return os;
}

int main()
{

    return 0;
}
